'''
#
# File: model.py
# Description: JHB Model objects
#
# Copyright 2012 Adam Meadows
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#
'''

from errors import DuplicateNameError, InvalidNameError, BalanceError

class Account(object):
    '''A bank account'''
    def __init__(self, name, description):
        self.name = name
        self.description = description
        self.category_dict = {}

    def add_category(self, name):
        '''Add a new category, if the name is not already used'''
        if name in self.category_dict:
            raise DuplicateNameError('Duplicate category name "%s"' % name)
        self.category_dict[name] = Category(name=name)
        return self.category_dict[name]

    def get_category(self, name):
        if name not in self.category_dict:
            raise InvalidNameError('No such Category "%s"' % name)
        return self.category_dict[name]

    def get_categories(self, active_only=True):
        '''Return all categories (sorted by name)'''
        categories = self.category_dict.values()
        if active_only:
            categories = [ c for c in categories if c.is_active() ]
        return sorted(categories, key=lambda x: x.name)

    def get_balance(self):
        return sum( c.balance for c in self.category_dict.values() )


class Category(object):
    '''A logical division of an Account'''
    def __init__(self, name):
        self.name = name
        self._active = True
        self.balance = 0.0

    def is_active(self):
        return self._active

    def deactivate(self):
        '''Mark the Category as no longer active'''
        if self.balance != 0.0:
            tmpl = 'Cannot deactivate %s, balance is non-zero'
            raise BalanceError(tmpl % self.name)
        self._active = False

    def activate(self):
        self._active = True

